<script setup>
/**
 * 商品编辑页面，每个部分在点击保存后都会保存当前部分
 */

import { ref, onMounted } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { convertToFormData } from '@/utilities/common';
import { useRoute } from 'vue-router';

import CommodityCategorySelect from './components/CommodityCategorySelect.vue';
import CommoditySKUEdit from './components/CommoditySKUEdit.vue';

import {
  getCommodityDetail,
  uploadCommodityMainImage,
  editCommodityMain,
  uploadCommoditySlideShowImage,
  editCommoditySlideShowImages
} from '@/apis/commodity';
import { baseURL } from '@/utilities/request';

const route = useRoute();
let commodityId;

onMounted(async () => {
  commodityId = route.query?.id;
  if (!commodityId) {
    ElMessage.error('没有要编辑的商品');
    return;
  }
  refreshCommodityDetail(commodityId);
});

/* 商品主信息 */
const mainModelRef = ref();
const mainModel = ref({});

let mainImageRaw;
const onMainImageSelectFile = (uploadFile) => {
  mainModel.value.mainImageUrl = URL.createObjectURL(uploadFile.raw);
  mainImageRaw = uploadFile.raw;
};

const rules = ref({
  commodityName: [
    { required: true, message: '请输入商品名称', trigger: 'blur' }
  ],
  categoryId: [{ required: true, message: '请选择商品分类', trigger: 'blur' }],
  intro: [{ required: true, message: '请输入商品简介', trigger: 'blur' }],
  manufacture: [{ required: true, message: '请输入制造商', trigger: 'blur' }]
});

const refreshCommodityDetail = async (commodityId) => {
  let respData = await getCommodityDetail({
    id: commodityId
  });
  respData = respData.data;

  // 重新赋值图片地址
  respData.main.mainImageUrl = `${baseURL}${respData.main.mainImageUrl}`;
  respData.slideShowImageList.forEach((element) => {
    element.imageUrl = `${baseURL}${element.imageUrl}`;
    element.url = element.imageUrl; // el-upload 组件列表展示时仅接受 url 的属性值
  });
  respData.skuList.forEach((element) => {
    element.skuImageUrl = `${baseURL}${element.skuImageUrl}`;
  });

  mainModel.value = respData.main;
  slideShowImageList.value = respData.slideShowImageList;
  skuTableData.value = respData.skuList;
};

// 保存商品主信息
const saveEditCommodity = async () => {
  await mainModelRef.value.validate();

  // 准备数据
  let reqData = JSON.parse(JSON.stringify(mainModel.value));

  // 上传图片
  if (mainImageRaw) {
    let uploadRespData = await uploadCommodityMainImage(
      convertToFormData({
        name: mainImageRaw.name,
        file: mainImageRaw
      })
    );
    reqData.mainImageUrl = uploadRespData.data;
  } else {
    reqData.mainImageUrl = reqData.mainImageUrl.replace(baseURL, ''); // 如果没有改变，则需要清除前面的服务器地址信息
  }

  // 发送请求
  let res = await editCommodityMain(reqData);
  ElMessage.success(res.msg);
  await refreshCommodityDetail(commodityId);
};

/* 商品轮播图片 */
const slideShowImageList = ref([]);
const onSlideShowImageSelectFile = (uploadFile) => {
  slideShowImageList.value.push({
    name: uploadFile.name,
    url: uploadFile.url,
    raw: uploadFile.raw
  });
};

const handleExceed = () => {
  ElMessage.error('最多只能上传 4 张图片');
};

const saveEditCommodityImages = () => {
  // 产生请求序列
  let uploadArr = slideShowImageList.value.map((item) => {
    if (item.id) {
      // 如果该图片没有重新选择，则直接返回一个 Promise.resolve 结果即可
      return Promise.resolve({
        data: item.url.replace(baseURL, '')
      });
    } else {
      // 如果该图片是新添加的，则返回上传的 Promise
      return uploadCommoditySlideShowImage(
        convertToFormData({
          name: item.name,
          file: item.raw
        })
      );
    }
  });

  // 同时全部上传
  Promise.all(uploadArr)
    .then(async (resultArr) => {
      ElMessage.success('轮播图全部上传成功');
      // 准备数据
      let imageItems = [];
      resultArr.forEach((value, index) => {
        imageItems.push({
          id: slideShowImageList.value[index].id || '',
          imageUrl: value.data,
          sortNum: index
        });
      });
      let reqData = {
        commodityId: mainModel.value.id,
        slideShowImageItems: imageItems
      };
      // 发送请求
      let res = await editCommoditySlideShowImages(reqData);
      ElMessage.success(res.msg);
      await refreshCommodityDetail(commodityId);
    })
    .catch((err) => {
      ElMessage.error(err);
    });
};

const isShowPrevieImage = ref(false);
const previewImageUrl = ref();
const handleImagePreview = (uploadFile) => {
  previewImageUrl.value = uploadFile.url;
  isShowPrevieImage.value = true;
};

/* SKU 信息 */
const skuTableData = ref([]);
const skuEditRef = ref();

const onCellClick = (row, column) => {
  if (column.no !== 0) {
    return;
  } else {
    // 当点击图片单元格时，预览图片
    previewImageUrl.value = row.skuImageUrl;
    isShowPrevieImage.value = true;
  }
};

const addSKU = () => {
  skuEditRef.value.open('edit', -1, {}, mainModel.value.id);
};

const editSKU = (scope) => {
  skuEditRef.value.open(
    'edit',
    scope.$index,
    JSON.parse(JSON.stringify(scope.row)),
    mainModel.value.id
  );
};

const deleteSKU = (scope) => {
  skuTableData.value.splice(scope.$index, 1);
};

const onFinishEditSKU = async () => {
  await refreshCommodityDetail(commodityId);
};
</script>
<template>
  <div class="container">
    <h2>编辑商品</h2>
    <div class="main-info-container">
      <div class="title-container">
        <h2 class="title">商品信息</h2>
        <div class="ops">
          <el-button @click="saveEditCommodity">保存修改</el-button>
        </div>
      </div>
      <el-form
        ref="mainModelRef"
        :model="mainModel"
        :rules="rules"
        label-width="100px"
        label-position="top"
      >
        <div class="main-image-container">
          <el-upload
            class="main-image-uploader"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="onMainImageSelectFile"
          >
            <img
              v-if="mainModel.mainImageUrl"
              :src="mainModel.mainImageUrl"
              class="main-image"
            />
            <el-icon v-else class="main-image-uploader-icon">
              <Plus />
            </el-icon>
          </el-upload>
        </div>
        <div class="info-container">
          <el-form-item
            class="input-item"
            label="商品名称"
            prop="commodityName"
          >
            <el-input v-model="mainModel.commodityName" />
          </el-form-item>
          <el-form-item
            class="input-item input-item-after"
            label="商品分类"
            prop="categoryId"
          >
            <commodity-category-select
              v-model="mainModel.categoryId"
            ></commodity-category-select>
          </el-form-item>
          <el-form-item class="input-item" label="制造商" prop="manufacture">
            <el-input v-model="mainModel.manufacture" />
          </el-form-item>
          <el-form-item label="简介" prop="intro">
            <el-input
              type="textarea"
              v-model="mainModel.intro"
              resize="none"
              :rows="3"
              :maxlength="50"
              :show-word-limit="true"
            />
          </el-form-item>
        </div>
      </el-form>
    </div>
    <div class="images-container">
      <div class="title-container">
        <h2 class="title">商品轮播图</h2>
        <div class="ops">
          <el-button @click="saveEditCommodityImages">保存修改</el-button>
        </div>
      </div>
      <div>
        <el-upload
          v-model:file-list="slideShowImageList"
          list-type="picture-card"
          :auto-upload="false"
          :on-change="onSlideShowImageSelectFile"
          :on-preview="handleImagePreview"
          :on-exceed="handleExceed"
          :limit="4"
        >
          <el-icon>
            <Plus />
          </el-icon>
        </el-upload>
      </div>
    </div>
    <div class="skus-container">
      <div class="title-container">
        <h2 class="title">SKU</h2>
        <div class="ops">
          <el-button @click="addSKU">新增 SKU</el-button>
        </div>
      </div>
      <el-table
        :data="skuTableData"
        style="width: 100%"
        @cell-click="onCellClick"
      >
        <el-table-column label="图片" width="180">
          <template #default="scope">
            <img
              style="width: 50px; height: 50px"
              :src="scope.row.skuImageUrl"
            />
          </template>
        </el-table-column>
        <el-table-column prop="skuName" label="名称" width="180" />
        <el-table-column prop="quantity" label="数量" width="180" />
        <el-table-column prop="price" label="价格" width="180" />
        <el-table-column label="操作">
          <template #default="scope">
            <el-button type="info" @click="editSKU(scope)">编辑</el-button>
            <el-button type="danger" @click="deleteSKU(scope)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <CommoditySKUEdit
      @finishEditSKU="onFinishEditSKU"
      ref="skuEditRef"
    ></CommoditySKUEdit>
    <!-- <div class="detail-container"></div> -->

    <el-dialog v-model="isShowPrevieImage" width="30%">
      <img style="width: 100%; height: 100%" :src="previewImageUrl" />
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.container {
  width: 1000px;
  height: 900px;
}

.title-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.main-info-container {
  .main-image-container {
    display: inline-block;
    vertical-align: top;
    width: 300px;
    height: 300px;

    .main-image-uploader {
      padding: 10px;

      .main-image {
        width: 280px;
        height: 280px;
        display: block;
      }

      :deep(.el-upload) {
        border: 1px dashed var(--el-border-color);
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
        transition: var(--el-transition-duration-fast);
      }

      :deep(.el-upload:hover) {
        border-color: var(--el-color-primary);
      }

      :deep(.el-icon.main-image-uploader-icon) {
        font-size: 28px;
        color: #8c939d;
        width: 280px;
        height: 280px;
        text-align: center;
      }
    }
  }

  .info-container {
    box-sizing: border-box;
    display: inline-block;
    vertical-align: top;
    padding: 10px;
    width: 700px;
    height: 300px;

    .input-item {
      display: inline-block;

      :deep(.el-input) {
        width: 330px;
      }
    }

    .input-item-after {
      margin-left: 20px;
    }
  }
}
</style>
